package utils

import (
	"bytes"
	"encoding/base64"
	"golang.org/x/image/font"
	"golang.org/x/image/font/opentype"
	"golang.org/x/image/math/fixed"
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"
	"log"
	"math/rand"
	"os"
	"time"
)

const (
	width     = 105                      // 图像宽度
	height    = 35                       // 图像高度
	count     = 200                      // 干扰线数量
	lineWidth = 2                        // 干扰线长度系数
	base64Pre = "data:image/jpg;base64," // Base64 前缀
)

// GenerateCaptchaImage 生成包含验证码的 Base64 图像字符串
func GenerateCaptchaImage(resultCode string) (string, error) {
	// 创建空白图像
	img := image.NewRGBA(image.Rect(0, 0, width, height))
	graphics := draw.Image(img)
	// 设置背景颜色为白色
	draw.Draw(img, img.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
	// 绘制边框
	borderColor := color.RGBA{A: 255} // 黑色边框
	drawBorder(graphics, borderColor)
	// 随机生成干扰线
	source := rand.NewSource(time.Now().UnixNano())
	random := rand.New(source)
	for i := 0; i < count; i++ {
		x1 := random.Intn(width - lineWidth - 1)
		y1 := random.Intn(height - lineWidth - 1)
		x2 := x1 + random.Intn(lineWidth)
		y2 := y1 + random.Intn(lineWidth)
		lineColor := getRandColor(150, 200)
		drawLine(graphics, x1, y1, x2, y2, lineColor)
	}
	// 绘制验证码文本
	textColor := color.RGBA{A: 255} // 黑色文字
	drawText(graphics, resultCode, textColor)
	// 将图像编码为 JPEG 格式
	var buf bytes.Buffer
	err := jpeg.Encode(&buf, img, nil)
	if err != nil {
		return "", err
	}
	// 转换为 Base64 编码
	base64Encoded := base64.StdEncoding.EncodeToString(buf.Bytes())
	return base64Pre + base64Encoded, nil
}

// drawBorder 绘制边框
func drawBorder(graphics draw.Image, borderColor color.Color) {
	for x := 0; x < width; x++ {
		graphics.Set(x, 0, borderColor)        // 上边框
		graphics.Set(x, height-1, borderColor) // 下边框
	}
	for y := 0; y < height; y++ {
		graphics.Set(0, y, borderColor)       // 左边框
		graphics.Set(width-1, y, borderColor) // 右边框
	}
}

// drawLine 绘制干扰线
func drawLine(graphics draw.Image, x1, y1, x2, y2 int, lineColor color.Color) {
	dx := x2 - x1
	dy := y2 - y1
	steps := customMax(abs(dx), abs(dy))
	xIncrement := float64(dx) / float64(steps)
	yIncrement := float64(dy) / float64(steps)
	x, y := float64(x1), float64(y1)
	for i := 0; i <= steps; i++ {
		graphics.Set(int(x+0.5), int(y+0.5), lineColor)
		x += xIncrement
		y += yIncrement
	}
}

// drawText 绘制验证码文本
func drawText(graphics draw.Image, text string, textColor color.Color) {
	// 定义字体文件路径列表
	fontPaths := []string{
		"/data/go-server/wx-user-boot/TimesNewRoman.ttf", // 初始路径
		"./TimesNewRoman.ttf",                            // 备用路径
	}
	var fontFace font.Face
	for _, fontPath := range fontPaths {
		// 尝试加载字体文件
		fontBytes, err := os.ReadFile(fontPath)
		if err != nil {
			continue
		}
		// 使用 opentype 解析字体
		ttfFont, err := opentype.Parse(fontBytes)
		if err != nil {
			continue
		}
		// 设置字体大小并创建字体 Face
		fontFace, err = opentype.NewFace(ttfFont, &opentype.FaceOptions{
			Size:    24, // 字体大小
			DPI:     72, // 分辨率
			Hinting: font.HintingVertical,
		})
		if err == nil {
			break // 成功创建字体 Face 后退出循环
		} else {
			log.Printf("无法创建字体 Face 于 '%s': %v", fontPath, err)
		}
	}
	xOffset := 10 // 初始 x 偏移
	yOffset := 26 // 初始 y 偏移
	for _, char := range text {
		point := fixed.Point26_6{
			X: fixed.Int26_6(xOffset * 64),
			Y: fixed.Int26_6(yOffset * 64),
		}
		d := &font.Drawer{
			Dst:  graphics,
			Src:  image.NewUniform(textColor),
			Face: fontFace,
			Dot:  point,
		}
		d.DrawString(string(char))
		xOffset += 23 // 字符间距
	}
}

// getRandColor 获取随机颜色
func getRandColor(fc, bc int) color.RGBA {
	// 创建一个新的随机数生成器
	source := rand.NewSource(time.Now().UnixNano())
	random := rand.New(source)
	// 生成随机 RGB 值
	r := uint8(fc + random.Intn(bc-fc))
	g := uint8(fc + random.Intn(bc-fc))
	b := uint8(fc + random.Intn(bc-fc))
	return color.RGBA{R: r, G: g, B: b, A: 255}
}

// abs 返回绝对值
func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}

// max 返回两个整数中的较大值
func customMax(a, b int) int {
	if a > b {
		return a
	}
	return b
}
